package cranim.simulation;

import cranim.simulation.units.AbstractBattleship;
import cranim.simulation.units.AbstractUnit;
import cranim.simulation.units.AbstractIonCannon;
import cranim.simulation.units.AbstractHeavyLaser;
import cranim.simulation.units.AbstractGaussCannon;
import cranim.simulation.units.AbstractSmallShieldDome;
import cranim.simulation.units.AbstractLargeCargo;
import cranim.simulation.units.AbstractDestroyer;
import cranim.simulation.units.AbstractRocketLauncher;
import cranim.simulation.units.AbstractHeavyFighter;
import cranim.simulation.units.AbstractLightLaser;
import cranim.simulation.units.AbstractSmallCargo;
import cranim.simulation.units.AbstractLargeShieldDome;
import cranim.simulation.units.AbstractSolarSatellite;
import cranim.simulation.units.AbstractDeathstar;
import cranim.simulation.units.AbstractBomber;
import cranim.simulation.units.AbstractCruiser;
import cranim.simulation.units.AbstractPlasmaTurret;
import cranim.simulation.units.AbstractColonialShip;
import cranim.simulation.units.AbstractEspionageProbe;
import cranim.simulation.units.AbstractLightFighter;
import cranim.simulation.units.AbstractBattlecruiser;
import cranim.simulation.units.AbstractRecycler;
import cranim.Constants;
import cranim.crparsing.ParseFleet;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Benedikt
 */
public class Fleet implements Constants{
        
    private int arms, shields, hull;
    private ArrayList<Unit> units;
    private ArrayList<Unit> lostUnits;
    private boolean isattacker;
    
    public Fleet(int[] techs, ParseFleet parsedFleet, boolean isattacker){
        this.isattacker = isattacker;
        arms = techs[ARMS];
        shields = techs[SHIELDS];
        hull = techs[HULL];
                
        units = new ArrayList<>();
        lostUnits = new ArrayList<>();
                
        AbstractUnit abstractSmallCargo = new AbstractSmallCargo();
        AbstractUnit abstractLargeCargo = new AbstractLargeCargo();
        AbstractUnit abstractLightFighter = new AbstractLightFighter();
        AbstractUnit abstractHeavyFighter = new AbstractHeavyFighter();
        AbstractUnit abstractCruiser = new AbstractCruiser();
        AbstractUnit abstractBattleship = new AbstractBattleship();
        AbstractUnit abstractColonialShip = new AbstractColonialShip();
        AbstractUnit abstractRecycler = new AbstractRecycler();
        AbstractUnit abstractEspionageProbe = new AbstractEspionageProbe();
        AbstractUnit abstractSolarSatellite = new AbstractSolarSatellite();
        AbstractUnit abstractBomber = new AbstractBomber();
        AbstractUnit abstractDestroyer = new AbstractDestroyer();
        AbstractUnit abstractDeathstar = new AbstractDeathstar();
        AbstractUnit abstractBattlecruiser = new AbstractBattlecruiser();
        
        AbstractUnit abstractRocketLauncher = new AbstractRocketLauncher();
        AbstractUnit abstractLightLaser = new AbstractLightLaser();
        AbstractUnit abstractHeavyLaser = new AbstractHeavyLaser();
        AbstractUnit abstractGaussCannon = new AbstractGaussCannon();
        AbstractUnit abstractIonCannon = new AbstractIonCannon();
        AbstractUnit abstractPlasmaTurret = new AbstractPlasmaTurret();
        AbstractUnit abstractSmallShieldDome = new AbstractSmallShieldDome();
        AbstractUnit abstractLargeShieldDome = new AbstractLargeShieldDome();
        
        for(int i = 0; i < parsedFleet.scargo; i++){
            units.add(new Ship(this, arms, shields, hull, abstractSmallCargo));
        }
        for(int i = 0; i < parsedFleet.lcargo; i++){
            units.add(new Ship(this, arms, shields, hull, abstractLargeCargo));
        }
        for(int i = 0; i < parsedFleet.lfighter; i++){
            units.add(new Ship(this, arms, shields, hull, abstractLightFighter));
        }
        for(int i = 0; i < parsedFleet.hfighter; i++){
            units.add(new Ship(this, arms, shields, hull, abstractHeavyFighter));
        }
        for(int i = 0; i < parsedFleet.cruiser; i++){
            units.add(new Ship(this, arms, shields, hull, abstractCruiser));
        }
        for(int i = 0; i < parsedFleet.bship; i++){
            units.add(new Ship(this, arms, shields, hull, abstractBattleship));
        }
        for(int i = 0; i < parsedFleet.colship; i++){
            units.add(new Ship(this, arms, shields, hull, abstractColonialShip));
        }
        for(int i = 0; i < parsedFleet.recycler; i++){
            units.add(new Ship(this, arms, shields, hull, abstractRecycler));
        }
        for(int i = 0; i < parsedFleet.probe; i++){
            units.add(new Ship(this, arms, shields, hull, abstractEspionageProbe));
        }
        for(int i = 0; i < parsedFleet.solsat; i++){
            units.add(new Ship(this, arms, shields, hull, abstractSolarSatellite));
        }
        for(int i = 0; i < parsedFleet.bomber; i++){
            units.add(new Ship(this, arms, shields, hull, abstractBomber));
        }
        for(int i = 0; i < parsedFleet.destroyer; i++){
            units.add(new Ship(this, arms, shields, hull, abstractDestroyer));
        }
        for(int i = 0; i < parsedFleet.deathstar; i++){
            units.add(new Ship(this, arms, shields, hull, abstractDeathstar));
        }
        for(int i = 0; i < parsedFleet.bcruiser; i++){
            units.add(new Ship(this, arms, shields, hull, abstractBattlecruiser));
        }
        if(!isattacker){
            for(int i = 0; i < parsedFleet.rlauncher; i++){
                units.add(new Unit(this, arms, shields, hull, abstractRocketLauncher));
            }
            for(int i = 0; i < parsedFleet.llaser; i++){
                units.add(new Unit(this, arms, shields, hull, abstractLightLaser));
            }  
            for(int i = 0; i < parsedFleet.hlaser; i++){
                units.add(new Unit(this, arms, shields, hull, abstractHeavyLaser));
            }  
            for(int i = 0; i < parsedFleet.gauss; i++){
                units.add(new Unit(this, arms, shields, hull, abstractGaussCannon));
            }  
            for(int i = 0; i < parsedFleet.ioncan; i++){
                units.add(new Unit(this, arms, shields, hull, abstractIonCannon));
            }
            for(int i = 0; i < parsedFleet.plasmatur; i++){
                units.add(new Unit(this, arms, shields, hull, abstractPlasmaTurret));
            }
            for(int i = 0; i < parsedFleet.sshield; i++){
                units.add(new Unit(this, arms, shields, hull, abstractSmallShieldDome));
            }
            for(int i = 0; i < parsedFleet.lshield; i++){
                units.add(new Unit(this, arms, shields, hull, abstractLargeShieldDome));
            }
        }
    }
    
    public Fleet(int[] techs, ArrayList<Unit> oldunits, ArrayList<Unit> oldlostunits, boolean isattacker){
        this.isattacker = isattacker;
        arms = techs[ARMS];
        shields = techs[SHIELDS];
        hull = techs[HULL];
                
        this.units = new ArrayList<>();
        for (Unit oldunit : oldunits){
            units.add(new Unit(oldunit, this));
        }
        this.lostUnits = new ArrayList<>();
        for (Unit oldlostunit : oldlostunits){
            lostUnits.add(new Unit(oldlostunit, this));
        }
    }
    
    public int getSize(){
        return units.size();
    }  
    
    public boolean isEmtpy(){
        return units.isEmpty();
    }
    
    public boolean isAttacker(){
        return isattacker;
    }
    
    public Unit getRandomUnit() {
        double totalUnits = units.size();
        int selectedUnit = (int)Math.round((totalUnits-1.0)*Math.random());
        return units.get(selectedUnit);
    }
    
    public List<Unit> getUnitsOfType(int unitID){
        List<Unit> unitList = new ArrayList<>();
        for(int i = 0; i < units.size(); i++){
            if(units.get(i).getType() == unitID){
                unitList.add(units.get(i));
            }
        }
        return unitList;
    }    
    
    public int getUnitNumber(Unit unit){
        return units.indexOf(unit);
    }
    
    public List<Unit> getUnits(){
        return units;
    }
    
    public void recharge(int shieldTech){
        for(int i = 0; i < units.size(); i++){
            units.get(i).rechargeShields(shieldTech);
        }
    }
    
    public void removeDestroyed(){
        ArrayList<Unit> unitList = new ArrayList<>();
        for(int i = 0; i < units.size(); i++){
            if(!units.get(i).getDestroyFlag()){
                unitList.add(units.get(i));
            }
            else{
                //System.out.println("Adding "+units.get(i).toString()+" to lost units");
                lostUnits.add(units.get(i));
            }
        }
        units = unitList;
    }
    
    public Fleet cloneFleet(){
        int[] techs = {arms, shields, hull};
        return new Fleet(techs, units, lostUnits, isattacker);
    }
}
